#! /bin/bash
z_path=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
z_file=${z_path}/z.dat

z_save() {
	readarray -t z_sorted < <(for a in "${z_history[@]}"; do echo "$a"; done | sort -u -r)
	rm -f "${z_file}"
	for i in "${z_sorted[@]}" ; do 
		echo $i >> "${z_file}"
	done
}

get_index() {
        # Get index by $*
        z_index=0

        while [ $z_index -lt ${#z_history[@]} ] ; do
                v=${z_history[$z_index]:3}
                no_space="$(echo -e "${v}" | sed -e 's/[[:space:]]*$//')"
                if [[ "$no_space" = "$*" ]] ; then
                        return
                fi
                z_index=`expr $z_index + 1`
        done

        z_index=-1
}


z_load_new() {
	if [ -f "${z_file}.n" ] ; then
		readarray z_history_new < "${z_file}.n"
	        z_index_n=0

        	while [ $z_index_n -lt ${#z_history_new[@]} ] ; do
	                v1=${z_history_new[$z_index_n]:3}
                	no_space1="$(echo -e "${v1}" | sed -e 's/[[:space:]]*$//')"
			get_index $no_space1
	                if [[ "$z_index" = "-1" ]] ; then
        			z_history+=("${z_history_new[$z_index_n]}")
			else
				num=${z_history[${z_index}]:0:3}
		                num1=${z_history_new[${z_index_n}]:0:3}
				if [[ $num1 -gt $num ]] ; then
	                		num=$num1
				fi

		                z_num=`printf "%03d" $num`
		                z_history[${z_index}]=${z_num}${z_history[${z_index}]:3}
			fi               
                	z_index_n=`expr $z_index_n + 1`
	        done

		rm -f "${z_file}.n"
		z_save
	fi
}

z_load() {
	if [ -f "${z_file}" ] ; then
		readarray z_history < "${z_file}"
	else
		z_history=
		touch "${z_file}"
	fi

	z_load_new
}

add_history() {
	if [[ -z $* ]] ; then
		return
	fi

	# Add $* into history.
	z_load
	get_index $*
	if [[ $z_index == -1 ]] ; then
	        # New $* added.
		z_history+=("001$*")
	else
		num=${z_history[${z_index}]:0:3}
		num=`expr $num + 1`
		z_num=`printf "%03d" $num`

		z_history[${z_index}]=${z_num}${z_history[${z_index}]:3}
	fi
	z_save
}

copy_to_machine() {
	# Copy into $1.
	cp -f "${z_path}/z.dat" "${z_path}/z.dat.n"
	scp "${z_path}/z" "${z_path}/z.dat.n" root@$1:/bin
	rm -f "${z_path}/z.dat.n"
	ssh $1
}

delete_history() {
	search_history $2 $3 $4 $5 $6 $7
	if [[ -z $z_select ]] ; then
		echo Cancelled.
		exit
	fi

	unset z_history[$z_index]
	z_save
	echo Deleted from history.
}

search_history() {
	# Search $* as part in histories
        z_load
        z_index=0
	z_default=-1

        while [ $z_index -lt ${#z_history[@]} ] ; do
                v=${z_history[$z_index]:3}
                no_space="$(echo -e "${v}" | sed -e 's/[[:space:]]*$//')"
		if [[ -n "$no_space" ]] ; then
	                if [[ "$no_space" == *"$*"* ]] ; then
				if [[ $z_default == -1 ]] ; then
					z_default=$z_index
				fi
	                        echo $z_index : $no_space
			fi
                fi
                z_index=`expr $z_index + 1`
        done

	if [[ $z_default == -1 ]] ; then
		echo Can not find $*.
		result=
		return
	fi

	read -p "Select the index:($z_default)" z_select

	if [[ -z "$z_select" ]] ; then
		z_index=$z_default
	else
		z_index=$z_select
	fi
		
	result=${z_history[$z_index]:3}
}



if [[ -z $1 ]] ; then
	echo
	echo ===== Run and record history =====
	echo " z [Command] [Args]	- Run the command and record"
	echo " z [SearchText]		- Search the texts and show history"
	echo " z [IP]			- Copy z and history data into another machine, and ssh to this machine"
	echo " z -a			- Select and add bash history into z historyi"
	echo " z -d			- Delete history"
	echo " z -l			- List first 20 lines of history"
	echo
	echo Note: Because some reason, do NOT support \" \' in the arguments.
	echo
	exit
fi

if [[ $1 == -l ]] ; then
	if [[ -z $2 ]] ; then
		head -n 20 "$z_file"
	else 
		cat "$z_file" | grep $2
	fi
elif [[ $1 == -a ]] ; then
	# Select and add bash history
	if [[ -z $2 ]] ; then
		echo Type the following:
		echo \ history 10
		echo \ \ # In the example, 534 is the command you need to add.
		echo
		echo \ z -a !534
	else
		add_history $2 $3 $4 $5 $6 $7 $8 $9 $10
	fi
elif [[ $1 == -d ]] ; then
	delete_history $*
elif [[ ! -z $2 ]] ; then
        # Run commands and add into history
        add_history "$@"

        "$@"
elif [[ $1 =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
	copy_to_machine $1
elif [[ $1 =~ ^[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
	copy_to_machine 10.86.$1
else 
	search_history $1
	if [[ ! -z $result ]] ; then
		add_history $result
		$result
	fi
fi


